#pragma once
#include "Log.hpp"
#include "Connection.hpp"
#include "TcpServer.hpp" //一会看看有没有问题。
#include "Common.hpp"
#include <unistd.h>
#include <sys/socket.h>
#include <cstdio>
#include <cstdlib>

using namespace LogModule;
class CallBack
{
    // using Connection = ConnModule::Connection;

public:
    static void HandlerRequest()
    {
        // 业务层相关回调
    }

    // 采用非阻塞读，轮询的方式进行，执行完后调用上方的业务处理函数
    static void reader(Connection *conn)
    {
        char buffer[1024];
        int socket = conn->GetSocket();
        while (true)
        {
            // 非阻塞读取。
            int n = recv(socket, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                conn->InReaderBuffer(buffer);
            }
            else if (n == 0)
            {
                // 对端关闭了连接
                logger(LogLevel::DEBUG, __FILE__, __LINE__) << "Connection closed by peer on socket " << socket;
                conn->_execpter(conn); // 调用异常处理清理连接
                return;                // 直接返回，不再继续处理
            }
            else
            {
                if (errno == EINTR)
                    continue;
                else if (errno == EAGAIN) // 缓冲区没数据
                    break;
                else
                {
                    logger(LogLevel::DEBUG, __FILE__, __LINE__) << "Recv Failed:" << strerror(errno);
                    conn->_execpter(conn);
                    return;
                }
            }
        }
        // logger(LogLevel::DEBUG, __FILE__, __LINE__) << "sockfd# " << conn->GetSocket() << ":\n"
        //           << conn->WriteBuffer() << strerror(errno);
        // 为了测试代码功能直接转接到发送
        conn->WriteBuffer() += conn->ReadBuffer();
        conn->ReadBuffer().clear();
        // 下面可以采用调用writer或者添加到事件监控中。
        conn->_writer(conn);
    }

    // 采用非阻塞写，轮询
    static void writer(Connection *conn)
    {
        while (true)
        {
            std::string &outbuff = conn->OutWriteBuffer();
            ssize_t n = write(conn->GetSocket(), outbuff.c_str(), outbuff.size());
            if (n > 0)
            {
                outbuff.erase(0, n);
                if (!outbuff.empty())
                    continue;
            }
            else
            {
                if (EINTR == errno)
                    continue;
                if (EAGAIN == errno)
                    break;
                else
                {
                    logger(LogLevel::DEBUG, __FILE__, __LINE__) << "Write Failed:" << strerror(errno);
                    conn->_execpter(conn);
                }
            }
        }
        // 走到这里，意味着什么？我们本轮发满了，但是数据可能没发完，为什么没发完呢？
        // 开启对conn->SockFd() EPOLLOUT的关心！！！！！， 如何开启对于特定一个connection对应的写事件关心呢？？？
        if (!conn->EmptyWriteBuff())
        {
            conn->_R->EnableReadWrite(conn->GetSocket(), true, true);
        }
        else
        {
            conn->_R->EnableReadWrite(conn->GetSocket(), true, false);
        }
    }

    static void excepter(Connection *conn)
    {
        // 1、取消对conn事件的关心
        conn->_R->RemoveConnction(conn->GetSocket());
        // 2、关闭文件描述符
        conn->Close();
        // 3、删除对应new空间
        delete (conn);
        return;
    }
};